
#ifndef _TY_STRING_H_
#define _TY_STRING_H_

#include <string.h>
#include <stdarg.h>
#include <stdio.h>

#include <iostream>


namespace ty
{

	template <int max_size>
	class string
	{
	private:
		typedef string< max_size > 	self;
		enum { MAX_SIZE = max_size };

		char		m_value[ MAX_SIZE + 1 ];
		int		m_len;

	public:
		/**
		 * @brief string 构造函数
		 */
		string( ) {/*m_len = 0;*/ }


		/**
		 * @brief ~string 默认析构函数
		 */
		~string( ) { }

		/**
		 * @brief string copy构造函数
		 *
		 * @param value
		 */
		string( const string& value )
		{
			strcpy( m_value, value.m_value );
			m_len = value.m_len;
		}

		string( self& value )
		{
			strcpy( m_value, value.value );
			m_len = value.m_len;
		}

		/**
		 * @brief string \0结束的构造函数
		 *
		 * @param value
		 */
		string( const char* value )
		{
			strncpy( m_value, value, MAX_SIZE );
			m_value[ MAX_SIZE ] = '\0';
			m_len = strlen( m_value );
		}

		/**
		 * @brief string 构造函数
		 *
		 * @param value 字符
		 */
		string( char value )
		{
			m_value[ 0 ] = value;
			m_value[ 1 ] = 0;
			m_len = strlen( m_value );
		}

		/**
		 * @brief length 返回字符串的长度
		 *
		 * @return
		 */
		inline int length( ) { return m_len; }

		/**
		 * @brief c_str 返回Zero结尾的只读字符串
		 *
		 * @return
		 */
		inline const char* c_str( ) const
		{
			return m_value;
		}

		/**
		 * @brief append 向尾部按照格式追加字符串
		 *
		 * @param fmt 格式,参考sprintf
		 * @param ... 格式需要的参数
		 *
		 * @return
		 */
		inline
			string& append( const char* fmt, ... )
		{
			va_list ap;
			va_start( ap, fmt );
			int n = vsnprintf( &m_value[ m_len ], MAX_SIZE - m_len, fmt, ap );
			va_end( ap );

			if ( n >= ( MAX_SIZE - m_len ) )
			{
				m_len = MAX_SIZE - 1;
			}
			else
			{
				m_len += n;
			}

			return *this;
		}

		/**
		 * @brief append 向尾部追加字符串
		 *
		 * @param value 追加的字符串
		 *
		 * @return
		 */
		inline
			string& append( const string& value )
		{
			strncat( m_value, value.m_value, MAX_SIZE - m_len );
			m_len = strlen( m_value );

			return *this;
		}

		/**
		 * @brief assign 赋值\0结束的字符串
		 *
		 * @param s \0结束的字符串
		 *
		 * @return
		 */
		inline
			string& assign( const char* s )
		{
			strncpy( m_value, s, MAX_SIZE );
			m_len = strlen( m_value );
			return *this;
		}


		/*
		inline
		string& append(const char* value)
		{
			strncat(m_value, value, MAX_SIZE - m_len);
			m_len = strlen(m_value);

			return *this;
		}
		*/

		/**
		 * @brief append 向尾部追加字符
		 *
		 * @param ch 带追加的字符
		 *
		 * @return
		 */
		inline
			string& append( char ch )
		{
			if ( m_len < MAX_SIZE )
			{
				m_value[ m_len++ ] = ch;
				m_value[ m_len ] = 0;
			}
			return *this;
		}

		/**
		 * @brief clear 清理字符串
		 */
		inline
			void clear( )
		{
			m_value[ 0 ] = 0;
			m_len = 0;
		}

		/**
		 * @brief size  返回字符串的最大长度
		 *
		 * @return
		 */
		inline
			int size( )
		{
			return MAX_SIZE;
		}

		/**
		 * @brief empty 判断字符串的长度是否为0
		 *
		 * @return
		 */
		inline
			bool empty( )
		{
			return m_len == 0;
		}


		/**
		 * @brief replace 替换字符串中的内容
		 *
		 * @param ptoken 需要替换的内容,匹配模式是完全匹配
		 * @param pvalue 替换之后的内容
		 *
		 * @return 替换成功则返回true,否则返回失败
		 */
		inline
			bool replace( const char* ptoken, const char* pvalue )
		{
			if ( !ptoken || !pvalue ) return false;

			int nplus = strlen( pvalue );
			int nsub = strlen( ptoken );

			char* pstart = m_value;
			while ( ( pstart = strstr( pstart, ptoken ) ) != NULL )
			{
				if ( ( m_len + nplus - nsub ) >= MAX_SIZE ) return false;

				memmove( pstart + nplus, pstart + nsub, m_len - ( pstart - m_value + nsub ) );
				memcpy( pstart, pvalue, nplus );

				m_len = m_len + nplus - nsub;
				m_value[ m_len ] = 0;
			}

			return true;
		}

		/**
		 * @brief << 重载操作符<<
		 *
		 * @param os
		 * @param s
		 *
		 * @return
		 */
		friend std::ostream& operator << ( std::ostream& os, string& s )
		{
			os << s.m_value;
			return os;
		}

		/**
		 * @brief + 重载操作符+为append操作
		 *
		 * @param lhs
		 * @param rhs
		 *
		 * @return
		 */
		inline friend
			string operator + ( const string& lhs, const string& rhs )
		{
			return string( lhs ).append( rhs );
		}

		inline friend
			string operator + ( const char* lhs, const string& rhs )
		{
			return string( lhs ).append( rhs );
		}

		inline friend
			string operator + ( const string& lhs, const char* rhs )
		{
			return string( lhs ).append( rhs );
		}

		inline friend
			string operator + ( char lhs, const string& rhs )
		{
			return string( lhs ).append( rhs );
		}

		inline friend
			string operator + ( const string& lhs, char rhs )
		{
			return string( lhs ).append( string( rhs ) );
		}

		inline
			string& operator += ( const string& value )
		{
			return append( value );
		}

		inline
			string& operator += ( const char* value )
		{
			string str( value );
			return append( str );
		}

		/**
		 * @brief [] 重载操作符[]，将字符串作为数组访问
		 *
		 * @param index
		 *
		 * @return
		 */
		inline
			char operator [] ( int index )
		{
			if ( index <= m_len )	return m_value[ index ];

			return 0;
		}

		/**
		 * @brief = 重载操作符=,判断两个字符串是否相同
		 *
		 * @param value
		 *
		 * @return
		 */
		inline
			string& operator = ( const string& value )
		{
			if ( this != &value )
			{
				strcpy( m_value, value.m_value );
				m_len = value.m_len;
			}

			return *this;
		}

		inline
			bool operator == ( const string& value ) const
		{
			if ( this != &value )
			{
				if ( m_len != value.m_len ) return false;
				return ( strcmp( m_value, value.m_value ) == 0 );
			}

			return true;
		}

		/**
		 * @brief < 重载操作符<，判断strcmp(this,value)<0
		 *
		 * @param value
		 *
		 * @return
		 */
		inline
			bool operator < ( const string& value ) const
		{
			if ( this != &value )
			{
				if ( m_len < value.m_len ) return true;
				if ( m_len > value.m_len ) return false;
				return ( strcmp( m_value, value.m_value ) < 0 );
			}

			return false;
		}

		/**
		 * @brief > 重载操作符>，判断strcmp(this, value) > 0
		 *
		 * @param value
		 *
		 * @return
		 */
		inline
			bool operator > ( const string& value ) const
		{
			if ( this != &value )
			{
				if ( m_len > value.m_len ) return true;
				if ( m_len < value.m_len ) return false;
				return ( strcmp( m_value, value.m_value ) > 0 );
			}

			return false;
		}
	};

	typedef string<8>		CString8;
	typedef string<16>		CString16;
	typedef string<32>		CString32;
	typedef string<64>		CString64;
	typedef string<128>		CString128;
	typedef string<256>		CString256;

};

#endif

